home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / CDTV / cdtvtools-11 / audio / audio2.c next >
Encoding:
C/C++ Source or Header  |  1991-06-21  |  13.5 KB  |  469 lines

  1. ;/* audio2.c - Execute me to compile me with Lattice 5.04
  2. ; NOTE: This code requires the IFF header include files IFF/iff.h
  3. ;       and IFF/8svx.h from the IFF toolkit disk which is available
  4. ;       from CATS.
  5. LC -b1 -cfistq -v -y -j73 audio2.c
  6. Blink FROM LIB:c.o,audio2.o TO audio2 LIBRARY LIB:LC.lib,LIB:Amiga.lib
  7. quit
  8. */
  9.  
  10. /* Audio2.c - 8SVX example - double buffers >128K samples
  11.  *
  12.  * Copyright (c) 1990 Commodore-Amiga, Inc.
  13.  *
  14.  * This example is provided in electronic form by Commodore-Amiga, Inc. for
  15.  * use with the 1.3 revisions of the Addison-Wesley Amiga reference manuals.
  16.  * The 1.3 Addison-Wesley Amiga Reference Manual series contains additional
  17.  * information on the correct usage of the techniques and operating system
  18.  * functions presented in this example.  The source and executable code of
  19.  * this example may only be distributed in free electronic form, via bulletin
  20.  * board or as part of a fully non-commercial and freely redistributable
  21.  * diskette.  Both the source and executable code (including comments) must
  22.  * be included, without modification, in any copy.  This example may not be
  23.  * published in printed form or distributed with any commercial product.
  24.  * However, the programming techniques and support routines set forth in
  25.  * this example may be used in the development of original executable
  26.  * software products for Commodore Amiga computers.
  27.  * All other rights reserved.
  28.  * This example is provided "as-is" and is subject to change; no warranties
  29.  * are made.  All use is at your own risk.  No liability or responsibility
  30.  * is assumed.
  31.  */
  32.  
  33. /* Lattice use lc -b1 -cfist -v -y. Link with lc.lib and amiga.lib   */
  34. /*----------------*/
  35. /*   INCLUDES     */
  36. /*----------------*/
  37. #include <exec/types.h>
  38. #include <exec/memory.h>
  39. #include <devices/audio.h>
  40. #include <libraries/dos.h>
  41. #include <libraries/dosextens.h>
  42. #include <graphics/gfxbase.h>
  43. #include <iff/iff.h>
  44. #include <iff/8svx.h>
  45. #include <proto/all.h>
  46. #include <stdlib.h>
  47. #include <stdio.h>
  48.  
  49. #define VHDR MakeID('V','H','D','R')
  50. #define BODY MakeID('B','O','D','Y')
  51. #define MY8S MakeID('8','S','V','X')
  52.  
  53. #ifdef LATTICE
  54. int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
  55. int chkabort(void) { return(0); }  /* really */
  56. #endif
  57.  
  58. void              kill8svx(char *);
  59. void              kill8(void);
  60.  
  61. /*--------------------*/               /* These globals are needed */
  62. /*   G L O B A L S    */               /* by the clean up routines */
  63. /*--------------------*/
  64. struct IOAudio     *AIOptr1,           /* Pointers to Audio IOBs      */
  65.                    *AIOptr2,
  66.                    *Aptr;
  67. struct Message     *msg;               /* Msg, port and device for    */
  68. struct MsgPort     *port,              /* driving audio               */
  69.                    *port1,*port2;
  70.        ULONG        device;
  71.        UBYTE       *sbase,*fbase;      /* For sample memory allocation */
  72.        ULONG        fsize,ssize;       /* and freeing                  */
  73. struct FileHandle  *v8handle;
  74.        UBYTE        chan1[]  = {  1 }; /* Audio channel allocation arrays */
  75.        UBYTE        chan2[]  = {  2 };
  76.        UBYTE        chan3[]  = {  4 };
  77.        UBYTE        chan4[]  = {  8 };
  78.        UBYTE       *chans[] = {chan1,chan2,chan3,chan4};
  79.  
  80.        BYTE          oldpri,c;            /* Stuff for bumping priority */
  81.        struct Task  *mt=0L;
  82.  
  83. /*-----------*/
  84. /*  M A I N  */
  85. /*-----------*/
  86. void main(int argc,char **argv)
  87. {
  88. /*-------------*/
  89. /* L O C A L S */
  90. /*-------------*/
  91.        char         *fname;               /* File name and data pointer*/
  92.        UBYTE        *p8data;              /* for file read.            */
  93.        ULONG         clock;               /* Clock constant            */
  94.        ULONG         length[2];           /* Sample lengths            */
  95.        BYTE          iobuffer[8],         /* Buffer for 8SVX header    */
  96.                     *psample[2];          /* Sample pointers           */
  97.        Chunk        *p8Chunk;             /* Pointers for 8SVX parsing */
  98.        Voice8Header *pVoice8Header;
  99.        ULONG         y,rd8count,speed;    /* Counters, sampling speed   */
  100.        ULONG         wakebit;             /* A wakeup mask              */
  101.  
  102. /*-------------*/
  103. /*   C O D E   */
  104. /*-------------*/
  105.  
  106. /*------------------------------*/
  107. /* Check Arguments, Initialize  */
  108. /*------------------------------*/
  109. fbase=0L;
  110. sbase=0L;
  111. AIOptr1=0L;
  112. AIOptr2=0L;
  113. port=0L;
  114. port1=0L;
  115. port2=0L;
  116. v8handle=0L;
  117. device=1L;
  118.  
  119. if (argc < 2)
  120.     {
  121.     kill8svx("No file name given.\n");
  122.     exit(1L);
  123.     }
  124. fname=argv[1];
  125.  
  126. /*---------------------------*/
  127. /* Initialize Clock Constant */
  128. /*---------------------------*/
  129. GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
  130. if(GfxBase==0L)
  131.     {
  132.     puts("Can't open graphics library\n");
  133.     exit(1L);
  134.     }
  135.  
  136. if(GfxBase->DisplayFlags & PAL) clock=3546895L;        /* PAL clock */
  137. else                            clock=3579545L;        /* NTSC clock */
  138.  
  139. if(GfxBase)
  140.     CloseLibrary( (struct Library *) GfxBase);
  141.  
  142. /*---------------*/
  143. /* Open the File */
  144. /*---------------*/
  145. v8handle= (struct FileHandle *) Open(fname,MODE_OLDFILE);
  146. if(v8handle==0)
  147.     {
  148.     kill8svx("Can't open 8SVX file.\n");
  149.     exit(1L);
  150.     }
  151.  
  152. /*-------------------------------------------*/
  153. /* Read the 1st 8 Bytes of the File for Size */
  154. /*-------------------------------------------*/
  155. rd8count=Read((BPTR)v8handle,iobuffer,8L);
  156. if(rd8count==-1)
  157.     {
  158.     kill8svx ("Read error.\n");
  159.     exit(1L);
  160.     }
  161. if(rd8count<8)
  162.     {
  163.     kill8svx ("Not an IFF 8SVX file, too short\n");
  164.     exit(1L);
  165.     }
  166.  
  167. /*-----------------*/
  168. /* Evaluate Header */
  169. /*-----------------*/
  170. p8Chunk=(Chunk *)iobuffer;
  171. if( p8Chunk->ckID != FORM )
  172.     {
  173.     kill8svx("Not an IFF FORM.\n");
  174.     exit(1L);
  175.     }
  176.  
  177. /*--------------------------------------------*/
  178. /* Allocate Memory for File and Read it in.   */
  179. /*--------------------------------------------*/
  180. fbase= (UBYTE *)AllocMem(fsize=p8Chunk->ckSize , MEMF_PUBLIC|MEMF_CLEAR);
  181. if(fbase==0)
  182.     {
  183.     kill8svx("No memory for read.\n");
  184.     exit(1L);
  185.     }
  186. p8data=fbase;
  187.  
  188. rd8count=Read((BPTR)v8handle,p8data,p8Chunk->ckSize);
  189. if(rd8count==-1)
  190.     {
  191.     kill8svx ("Read error.\n");
  192.     exit(1L);
  193.     }
  194. if(rd8count<p8Chunk->ckSize)
  195.     {
  196.     kill8svx ("Malformed IFF, too short.\n");
  197.     exit(1L);
  198.     }
  199. /*-------------------*/
  200. /* Evaluate IFF Type */
  201. /*-------------------*/
  202. if(MakeID( *p8data, *(p8data+1) , *(p8data+2) , *(p8data+3) ) != MY8S )
  203.     {
  204.     kill8svx("Not an IFF 8SVX file.\n");
  205.     exit(1L);
  206.     }
  207.  
  208. /*----------------------*/
  209. /* Evaluate 8SVX Chunks */
  210. /*----------------------*/
  211.  
  212. p8data=p8data+4;
  213.  
  214. while( p8data < fbase+fsize )
  215.   {
  216.   p8Chunk=(Chunk *)p8data;
  217.  
  218.   switch(p8Chunk->ckID)
  219.     {
  220.     case VHDR:
  221.       /*------------------------------------------------*/
  222.       /* Get a pointer to the 8SVX header for later use */
  223.       /*------------------------------------------------*/
  224.       pVoice8Header=(Voice8Header *)(p8data+8L);
  225.       break;
  226.     case BODY:
  227.  
  228.       /*-------------------------------------------------*/
  229.       /* Create pointers to 1-shot and continuous parts  */
  230.       /* for the top octave and get length. Store them.  */
  231.       /*-------------------------------------------------*/
  232.         psample[0] = (BYTE *)(p8data + 8L);
  233.         psample[1] = psample[0] + pVoice8Header->oneShotHiSamples;
  234.         length[0] = (ULONG)pVoice8Header->oneShotHiSamples;
  235.         length[1] = (ULONG)pVoice8Header->repeatHiSamples;
  236.         break;
  237.  
  238.     default:
  239.       break;
  240.     }
  241.  
  242.     /* end switch */
  243.  
  244.   p8data = p8data + 8L + p8Chunk->ckSize;
  245.  
  246.   if(p8Chunk->ckSize&1L == 1)
  247.       p8data++;
  248.   }
  249.  
  250. /* Play either the one-shot or continuous, not both */
  251. if  (length[0]==0)
  252.     y=1;
  253. else
  254.     y=0;
  255.  
  256. /*---------------------------------------*/
  257. /* Allocate chip memory for samples and  */
  258. /* copy from read buffer to chip memory. */
  259. /*---------------------------------------*/
  260. if(length[y]<=102400)ssize=length[y];
  261. else                 ssize=102400;
  262.  
  263. sbase=(UBYTE *)AllocMem( ssize , MEMF_CHIP | MEMF_CLEAR);
  264. if(sbase==0)
  265.     {
  266.     kill8svx("No chip memory.\n");
  267.     exit(1L);
  268.     }
  269. CopyMem(psample[y],sbase,ssize);
  270. psample[y]+=ssize;
  271.  
  272. /*----------------------------------*/
  273. /* Calculate playback sampling rate */
  274. /*----------------------------------*/
  275. speed =  clock / pVoice8Header->samplesPerSec;
  276.  
  277. /*-------------------*/
  278. /* Bump our priority */
  279. /*-------------------*/
  280. mt=FindTask(NULL);
  281. oldpri=SetTaskPri(mt,21);
  282.  
  283. /*--------------------------------*/
  284. /* Allocate two audio I/O blocks  */
  285. /*--------------------------------*/
  286. AIOptr1=(struct IOAudio *)
  287.       AllocMem( sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);
  288. if(AIOptr1==0)
  289.     {
  290.     kill8svx("No IO memory\n");
  291.     exit(1L);
  292.     }
  293.  
  294. AIOptr2=(struct IOAudio *)
  295.       AllocMem( sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);
  296. if(AIOptr2==0)
  297.     {
  298.     kill8svx("No IO memory\n");
  299.     exit(1L);
  300.     }
  301.  
  302. /*----------------------*/
  303. /* Make two reply ports */
  304. /*----------------------*/
  305. port1=CreatePort(0,0);
  306. if(port1==0)
  307.     {
  308.     kill8svx("No port\n");
  309.     exit(1L);
  310.     }
  311. port2=CreatePort(0,0);
  312. if(port2==0)
  313.     {
  314.     kill8svx("No port\n");
  315.     exit(1L);
  316.     }
  317.  
  318. c=0;
  319. while(device!=0 && c<4)
  320.   {
  321.   /*---------------------------------------*/
  322.   /* Set up audio I/O block for channel    */
  323.   /* allocation and Open the audio device  */
  324.   /*---------------------------------------*/
  325.   AIOptr1->ioa_Request.io_Message.mn_ReplyPort   = port1;
  326.   AIOptr1->ioa_Request.io_Message.mn_Node.ln_Pri = 128;  /* No stealing! */
  327.   AIOptr1->ioa_AllocKey                          = 0;
  328.   AIOptr1->ioa_Data                              = chans[c];
  329.   AIOptr1->ioa_Length                            = 1;
  330.  
  331.   device=OpenDevice("audio.device",0L,(struct IORequest *)AIOptr1,0L);
  332.   c++;
  333.   }
  334. if(device!=0)
  335.     {
  336.     kill8svx("No channel\n");
  337.     exit(1L);
  338.     }
  339.  
  340. /*-------------------------------------------*/
  341. /* Set Up Audio IO Blocks for Sample Playing */
  342. /*-------------------------------------------*/
  343. AIOptr1->ioa_Request.io_Command                =CMD_WRITE;
  344. AIOptr1->ioa_Request.io_Flags                  =ADIOF_PERVOL;
  345. /*--------*/
  346. /* Volume */
  347. /*--------*/
  348. AIOptr1->ioa_Volume=60;
  349. /*---------------*/
  350. /* Period/Cycles */
  351. /*---------------*/
  352. AIOptr1->ioa_Period =(UWORD)speed;
  353. AIOptr1->ioa_Cycles =1;
  354.  
  355. *AIOptr2 = *AIOptr1;   /* Make sure we have the same allocation keys, */
  356.                        /* same channels selected and same flags       */
  357.                        /* (but different ports...)                    */
  358. AIOptr1->ioa_Request.io_Message.mn_ReplyPort   = port1;
  359. AIOptr2->ioa_Request.io_Message.mn_ReplyPort   = port2;
  360.  
  361. /*--------*/
  362. /*  Data  */
  363. /*--------*/
  364. AIOptr1->ioa_Data            =(UBYTE *)sbase;
  365. AIOptr2->ioa_Data            =(UBYTE *)sbase + 51200;
  366.  
  367. /*-----------------*/
  368. /*  Run the sample */
  369. /*-----------------*/
  370. if(length[y]<=102400)
  371.   {
  372.   AIOptr1->ioa_Length=length[y];         /* No double buffering needed */
  373.   BeginIO((struct IORequest *)AIOptr1);  /* Begin the sample, wait for */
  374.   wakebit=0L;                            /* it to finish, then quit.   */
  375.   wakebit=Wait(1 << port1->mp_SigBit);
  376.   msg=GetMsg(port1);
  377.   }
  378. else
  379.   {
  380.   length[y]-=102400;                    /* It's a real long sample so  */
  381.   AIOptr1->ioa_Length=51200L;           /* double buffering is needed  */
  382.   AIOptr2->ioa_Length=51200L;
  383.   BeginIO((struct IORequest *)AIOptr1); /* Start up the first 2 blocks... */
  384.   BeginIO((struct IORequest *)AIOptr2);
  385.   Aptr=AIOptr1;
  386.   port=port1;                           /* Set the switch... */
  387.  
  388.   while(length[y]>0)
  389.     {                                   /* We Wait() for one IO to finish, */
  390.     wakebit=Wait(1 << port->mp_SigBit); /* then reuse the IO block & queue */
  391.     msg=GetMsg(port);                   /* it up again while the 2nd IO    */
  392.                                         /* block plays. Switch and repeat. */
  393.     /* Set length of next IO block */
  394.     if(length[y]<=51200)  Aptr->ioa_Length=length[y];
  395.     else                  Aptr->ioa_Length=51200L;
  396.  
  397.     /* Copy sample fragment from read buffer to chip memory */
  398.     CopyMem(psample[y],Aptr->ioa_Data,Aptr->ioa_Length);
  399.  
  400.     /* Adjust size and pointer of read buffer*/
  401.     length[y]-=Aptr->ioa_Length;
  402.     psample[y]+=51200;
  403.  
  404.     BeginIO((struct IORequest *)Aptr);
  405.  
  406.     if(Aptr==AIOptr1)
  407.          {Aptr=AIOptr2;                  /* This logic handles switching  */
  408.           port=port2;                    /* between the 2 IO blocks and   */
  409.          }                               /* the 2 ports we are using.     */
  410.     else {Aptr=AIOptr1;
  411.           port=port1;
  412.          }
  413.     }
  414.  
  415.   /*-------------------------------------------------*/
  416.   /* OK we are at the end of the sample so just wait */
  417.   /* for the last two parts of the sample to finish  */
  418.   /*-------------------------------------------------*/
  419.   wakebit=Wait(1 << port->mp_SigBit);
  420.   msg=GetMsg(port);
  421.  
  422.   if(Aptr==AIOptr1)
  423.        {Aptr=AIOptr2;                  /* This logic handles switching  */
  424.         port=port2;                    /* between the 2 IO blocks and   */
  425.        }                               /* the 2 ports we are using.     */
  426.   else {Aptr=AIOptr1;
  427.         port=port1;
  428.        }
  429.  
  430.   wakebit=Wait(1 << port->mp_SigBit);
  431.   msg=GetMsg(port);
  432.  
  433.   }
  434.  
  435. kill8();
  436. exit(0L);
  437. }
  438.  
  439. /*----------------*/
  440. /* Abort the Read */
  441. /*----------------*/
  442. void
  443. kill8svx(kill8svxstring)
  444. char *kill8svxstring;
  445. {
  446. puts(kill8svxstring);
  447. kill8();
  448. }
  449.  
  450. /*-------------------------*/
  451. /* Return system resources */
  452. /*-------------------------*/
  453. void
  454. kill8()
  455. {
  456. if(mt!=0)       SetTaskPri(mt,oldpri);
  457.  
  458. if(v8handle!=0) Close((BPTR)v8handle);
  459. if(fbase !=0)   FreeMem(fbase,fsize);
  460. if(sbase !=0)   FreeMem (sbase, ssize);
  461.  
  462. if(device ==0)  CloseDevice((struct IORequest *)AIOptr1);
  463. if(port1  !=0)  DeletePort(port1);
  464. if(port2  !=0)  DeletePort(port2);
  465. if(AIOptr1!=0)  FreeMem( AIOptr1,sizeof(struct IOAudio) );
  466. if(AIOptr2!=0)  FreeMem( AIOptr2,sizeof(struct IOAudio) );
  467. }
  468.  
  469.